import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class FixedSizeThreadPool  {

    // 1. 仓库
    private BlockingDeque<Runnable> blockingDeque;

    // 2. 线程集合
    private List<Thread> workers;

    // 3. 干活线程
    public static class Worker extends Thread{

        private FixedSizeThreadPool pool;

        public Worker(FixedSizeThreadPool pool) {
            this.pool = pool;
        }

        @Override
        public void run() {

            // 开始工作
            while (this.pool.isWorking || this.pool.blockingDeque.size() > 0){

                Runnable task = null;

                // 从队列中拿东西，需要的是阻塞
                try {
                    if (this.pool.isWorking){
                        task = this.pool.blockingDeque.take();
                    }
                    else{
                        task = this.pool.blockingDeque.poll();
                    }

                } catch (InterruptedException e) {
//                    e.printStackTrace();
                    System.out.println("一个线程被中断");
                }

                if (task != null){
                    task.run();
                    System.out.println("线程：" + Thread.currentThread().getName() + "执行");
                }

            }


        }
    }

    // 4. 初始化参数
    public FixedSizeThreadPool(int poolSize, int taskSize) {
        if (poolSize <= 0 || taskSize <= 0)
            throw new IllegalArgumentException("非法参数");

        this.blockingDeque = new LinkedBlockingDeque<>(taskSize);
        this.workers = Collections.synchronizedList(new ArrayList<>());

        for (int i = 0; i < poolSize; i++){
            Worker worker = new Worker(this);
            worker.start();
            workers.add(worker);
        }
    }

    // 5. 提交任务到仓库
    public boolean submit(Runnable task){
        if (isWorking){
            return this.blockingDeque.offer(task);
        }
        return false;
    }


    // 6. 关闭线程池方法
    // a. blockingDeque 仓库停止接收任务
    // b. 一旦仓库还有任务，继续执行
    // c. 一旦任务阻塞， 我要就要去中断

    private volatile boolean isWorking = true;

    public void shutDown(){

        isWorking = false;
        for(Thread thread : workers){
            if (thread.getState().equals(Thread.State.BLOCKED)){
                thread.interrupt();
            }
        }

    }

    public static void main(String[] args) {
        FixedSizeThreadPool pool = new FixedSizeThreadPool(3, 6);
        for (int i = 0; i < 6; i++){
            pool.submit(() -> {
                System.out.println("放入一个线程a。");
                try {
                    Thread.sleep(1000 * 2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

        }

        pool.shutDown();


    }





}
